﻿#pragma once
//客户端检测模块
#include"dataManger.hpp"
#include"util.hpp"
#include "httplib.h"
#include <Windows.h>
#include <chrono>
namespace Cloud
{
#define CHECKPATH "./Backup/"
#define ServerIP "106.54.0.164"
#define ServerPort 9090
#define BACKUP_REQ_PATH "/backup/"
	class Checker
	{
		std::string getTag(std::string& e)const 
		{
			fileUtil f1(e);
			return f1.filename() + std::to_string(f1.getModifyTime()) + std::to_string(f1.fileSize());
		}
		//上传接口
		bool upload(std::string& e) 
		{
			fileUtil f1(e);
			httplib::MultipartFormData data;
			data.name = "file";
			data.filename = f1.filename();
			f1.getContent(&data.content);
			data.content_type = "application/octet-stream";
			httplib::MultipartFormDataItems item;
			item.push_back(data);
			std::string str = std::string("username=") + _username + "; " + "password=" + _password;
			std::string cook = "Cookie";
			httplib::Headers header;
			header.insert(std::make_pair(cook, str));
			bool ret = true;
			decltype(std::chrono::high_resolution_clock::now()) start,end;
			try
			{
				  start = std::chrono::high_resolution_clock::now();
				 auto res = client.Post(BACKUP_REQ_PATH, header, item);
				  end = std::chrono::high_resolution_clock::now();
				 if (!res ||res->status/100 != 2)
					 ret = false;
				 else ret = true;
			}
			catch (const std::exception&e)
			{
				std::cout << e.what() << std::endl;
				exit(-1);
			}
			std::chrono::duration<double> diff = end - start;
			std::cout << f1.filename() << " 大小:" << f1.fileSize() << " 时间:" << diff.count() << " 平均速率:" << (f1.fileSize() / 1024.0) / diff.count() << " kb/s" << std::endl;
			return ret;
		}
		void menu()
		{
			int option;
			do {
				std::cout << "\t\t0. 退出" << std::endl;
				std::cout << "\t\t1. 登录" << std::endl;
				std::cout << "\t\t2. 注册" << std::endl;
				std::cout << "请输入你的选择:";
				(std::cin >> option).get();
				switch (option)
				{
				case 0:
					std::cout << "退出" << std::endl;
					exit(-1);
					break;
				case 1:
				case 2:
				{
					std::cout << "username: ";
					std::getline(std::cin, _username);
					std::cout << "password: ";
					std::getline(std::cin, _password);
					httplib::Params par;
					par.insert(std::make_pair("username", _username));
					par.insert(std::make_pair("password",_password));
					if (option == 1)
					{
						auto res = client.Post("/login/login/", par);
						if (res->status == 302 || res->status == 301)
						{
							std::cout << "登录成功!" << std::endl;
							return;
						}
						else
							std::cout << "登录失败!" << std::endl;
					}
					else
					{
						auto res = client.Post("/login/enroll/", par);
						if (res->status == 302||res->status==301)
						{
							std::cout << "注册成功!" << std::endl;
							return;
						}
						else
							std::cout << "注册失败!" << std::endl;
					}
				}break;
				default :
					std::cout << "输入有误,重新输入" << std::endl;
				}
			} while (option);
			system("cls");
		}
	public:
		Checker(const std::string& path = CHECKPATH) :_checkPath(path),client(ServerIP,ServerPort) {
		}
		void operator()()
		{
			menu();
			while (true)
			{
				//1.获取检测路径中的所有文件
				fileUtil f1(_checkPath);
				if (f1.exists() == false)
					f1.createDirectory();
				std::vector<std::string> array;
				f1.scanDirectory(&array);
				//2. 开始检测
				for (auto& e : array)
				{
					//1.检测文件是否是否需要备份
					bool flag = false;
					if (DataManger::getInstance().hasFileMessage(e) == false)
					{
						//新增文件
						flag = true;
						std::string newTag = getTag(e);
						fileMessage f1(e, newTag);
						DataManger::getInstance().insert(f1);
					}
					else
					{
						//文件存在
						std::string newTag = getTag(e);
						fileMessage tmp;
						tmp = DataManger::getInstance().getOneByRealPath(e);
						if (tmp.fileId != newTag)
						{
							//文件被修改,重新上传
							tmp.fileId = newTag;
							DataManger::getInstance().update(tmp);
							flag = true;
						}
					}
					//将文件进行上传
					if (flag)
						upload(e);
				}
				std::this_thread::sleep_for(std::chrono::milliseconds(5000));
			}
		}
	private:
		std::string _checkPath;
		std::string _username;
		std::string _password;
		httplib::Client client;
	};
}